Omar Faruk
09/05/2025, 11:28 AMMarvin
09/05/2025, 11:28 AMMarvin
09/05/2025, 11:29 AMprefect.deployments.steps.utility.run_shell_script
step.
A few tips:
- Use script: |
for multi-line content.
- Use env:
to set environment variables for the script.
- Set expand_env_vars: true
if you want $VAR
or ${VAR}
in your script to be expanded from the environment.
- Keep your shell syntax POSIX-compatible (sh
) unless you’re sure of the shell; simple `if`/`else` with [ ]
works well.
- The correct step path in 3.x is prefect.deployments.steps.utility.run_shell_script
.
Example with conditional logic:
build:
- prefect.deployments.steps.utility.run_shell_script:
id: prechecks
directory: .
script: |
set -euo pipefail
echo "Starting prechecks for ${PREFECT_DEPLOYMENT_NAME:-unknown}"
if [ "${RUN_DB_MIGRATIONS:-false}" = "true" ]; then
echo "Running database migrations..."
alembic upgrade head
else
echo "Skipping database migrations."
fi
if [ -n "${FEATURE_FLAG:-}" ]; then
echo "Feature flag is set to: ${FEATURE_FLAG}"
else
echo "Feature flag not set."
fi
echo "Done."
env:
RUN_DB_MIGRATIONS: "true"
FEATURE_FLAG: "beta"
expand_env_vars: true
stream_output: true
Alternative using a folded scalar (>-
) if you prefer a single logical line (YAML will fold newlines to spaces; generally |
is safer for scripts):
build:
- prefect.deployments.steps.utility.run_shell_script:
script: >-
set -e;
if [ "${ENVIRONMENT:-dev}" = "prod" ]; then
echo "Doing prod setup";
else
echo "Doing non-prod setup";
fi
env:
ENVIRONMENT: "prod"
expand_env_vars: true
Docs:
- run_shell_script API: prefect.deployments.steps.utility.run_shell_script
If you’re hitting a YAML parsing or quoting issue, paste your current prefect.yaml
snippet and I’ll help fix the indentation/quoting.Omar Faruk
09/05/2025, 11:33 AMMarvin
09/05/2025, 11:33 AMMarvin
09/05/2025, 11:35 AMprefect.deployments.steps.utility.run_shell_script
, not prefect.deployments.steps.run_shell_script
.
2) Avoid a trailing newline in stdout
- If you plan to use this step’s output as a Docker tag (or similar), echo
will include a newline. Prefer:
- printf '%s' "$CLEAN_BRANCH_NAME"
(portable) instead of echo
.
3) Ensure you’re in a git repo (or set directory)
- git rev-parse --abbrev-ref HEAD
will fail if the working directory isn’t a Git repo. Either:
- Run a prior pull/clone step, or
- Set directory:
to the repo path.
4) expand_env_vars
is optional here
- The shell will expand $CI_COMMIT_REF_NAME
already. You can keep expand_env_vars: true
, but it’s not required.
Corrected example:
- prefect.deployments.steps.utility.run_shell_script:
id: get-branch-name
script: |
if [ -n "$CI_COMMIT_REF_NAME" ]; then
BRANCH_NAME="$CI_COMMIT_REF_NAME"
else
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
fi
# Clean the branch name for a valid Docker tag
CLEAN_BRANCH_NAME=$(echo "$BRANCH_NAME" \
| tr '/' '-' \
| tr '[:upper:]' '[:lower:]' \
| sed 's/[^a-z0-9._-]/-/g' \
| sed 's/^-*//' \
| sed 's/-*$//')
# Print without a trailing newline so consumers (e.g., Docker tag) don't break
printf '%s' "$CLEAN_BRANCH_NAME"
stream_output: false
expand_env_vars: false
# directory: /path/to/git/repo # uncomment if needed
Tip for using the result later in your prefect.yaml:
- Reference it as {{ get-branch-name.stdout }}
(note: if you use echo
, you’ll get a trailing newline).
Docs:
- run_shell_script API: prefect.deployments.steps.utility.run_shell_script
- YAML/templating basics: prefect.yaml how-to
If you’re seeing a specific error message, share it and I’ll pinpoint the exact cause.Omar Faruk
09/05/2025, 11:57 AMMarvin
09/05/2025, 11:57 AMMarvin
09/05/2025, 11:59 AMif
, Prefect tries to execute a program named if
, which fails.
Fix: invoke a shell explicitly (bash or sh) and pass your multi-line script to it. Also use the correct step path in 3.x.
Example:
- prefect.deployments.steps.utility.run_shell_script:
id: get-branch-name
script: |
bash -lc "
set -euo pipefail
if [ -n \"${CI_COMMIT_REF_NAME:-}\" ]; then
BRANCH_NAME=\"${CI_COMMIT_REF_NAME}\"
else
BRANCH_NAME=\$(git rev-parse --abbrev-ref HEAD)
fi
CLEAN_BRANCH_NAME=\$(echo \"\$BRANCH_NAME\" \
| tr '/' '-' \
| tr '[:upper:]' '[:lower:]' \
| sed 's/[^a-z0-9._-]/-/g' \
| sed 's/^-*//' \
| sed 's/-*$//')
# Print without a trailing newline
printf '%s' \"\$CLEAN_BRANCH_NAME\"
"
stream_output: false
expand_env_vars: false
# directory: /path/to/git/repo # set if needed for git commands
Notes:
- Using bash -lc "<script>"
ensures your multi-line conditional runs in a shell.
- Double quotes around the script let environment variables expand; inner double quotes are escaped.
- You can swap bash
for sh
if bash isn’t available.
- expand_env_vars
isn’t required here—the shell expands $VAR
.
Docs: prefect.deployments.steps.utility.run_shell_script